home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
PACKET
/
PMPSRC11.ZIP
/
LEVEL1TX.C
< prev
next >
Wrap
Text File
|
1991-07-30
|
6KB
|
257 lines
/*
level1.c -- Level 1 synchronous transmission routines
Poor Man's Packet (PMP)
Copyright (c) 1991 by Andrew C. Payne All Rights Reserved.
Permission to use, copy, modify, and distribute this software and its
documentation without fee for NON-COMMERCIAL AMATEUR RADIO USE ONLY is hereby
granted, provided that the above copyright notice appear in all copies.
The author makes no representations about the suitability of this software
for any purpose. It is provided "as is" without express or implied warranty.
07/24/89
Andrew C. Payne
*/
/* ----- Includes ----- */
#include <stdio.h>
#include <alloc.h>
#include <dos.h>
#include "pmp.h"
#include "ports.h"
#include "crc.h"
/* ----- External Assembly Routines ----- */
extern word timer(void);
extern word transit(word when);
#define MAXTXQUEUE 50 /* max size of TXQueue */
/* ----- Local Variables ----- */
static struct ax25_level1 *TXQueue[MAXTXQUEUE]; /* Transmit queue */
static int TXQSize; /* number of items in queue */
int TXQBytes; /* total bytes in queue */
static int bitsent; /* # of bits sent */
/* ----- CRC Generation and Checking ----- */
/* CRCCheck(packet)
Given a packet, generates a CRC, checks with existing CRC, and sets
valid CRC.
*/
int CRCCheck(struct ax25_level1 *packet)
{
word crc;
int len; /* packet length, data bytes */
int i;
byte *p,t;
word q;
p = packet->data; /* pointer to data */
len = packet->len-2; /* length less CRC bytes */
/* compute CRC */
crc = 0xffff; /* initialize */
for(i=0; i<len; i++) {
t = *p++ ^ (crc & 0xff);
crc >>= 8;
crc ^= crc_table[t];
}
q = ~crc;
crc = *((word *)p); /* fetch existing */
*((word *)p) = q; /* store computed one */
return crc == q; /* return OK or not OK */
}
/* ----- Clock Skewing ----- */
/* ClockAdjust(bitcount)
Speeds up the BIOS clock depending on the number of bits specified.
*/
void ClockAdjust(int bitcount)
{
if(ClockSkew) {
bitcount = (bitcount / BITSPERTICK) - 1;
while(bitcount-- > 0)
geninterrupt(8); /* BIOS timer */
}
}
/* ----- Transmission Subroutines ----- */
/* sendflags(from,count)
Sends 'count' opening flags, synced with the transition at time
'from'. Returns time of last transition.
*/
static word sendflags(register word from, int count)
{
while(count--) {
transit(from -= BITTIME);
transit(from -= BITTIME*7);
}
bitsent += 8;
return from; /* time of last transition */
}
/* sendpacketdata(from,p)
Given a data packet, sends data packet synced with the transition
at time 'from'. Returns the time of the last transition.
NOTE: the 'c' variable MUST be an integer size.
*/
static word sendpacketdata(word from, struct ax25_level1 *packet)
{
int len; /* bytes left to send */
byte *p; /* pointer to data */
word c; /* current character to transmit */
int bit; /* bits left in c */
int count; /* count of one bits */
/* initialize pointers and counters */
len = packet->len;
p = packet->data;
/* send the packet */
bit = 0;
while(TRUE) {
count = 0;
/* find next zero bit, or five consecutive ones */
do {
if(!bit) { /* end of byte? */
if(len-- == 0) {
if(count == 5) {
transit(from -= BITTIME * 6);
bitsent += 6;
return from;
} else
return from - count * BITTIME;
}
c = *p++; /* get next byte */
bit = 7;
} else { /* else, next in next bit */
c >>= 1;
bit--;
}
count++;
} while(count < 6 && (c & 1));
/* if stuffed zero, undo last bit */
if(count == 6) {
bit++;
c <<= 1;
}
/* make next transition */
transit(from -= count * BITTIME);
bitsent += count;
}
}
/* ----- Transmitter Control ----- */
/* TXKey(state)
Sets the transmitter state to the state given (TRUE = 1 = keyup).
Updates the status line on the screen.
*/
void TXKey(int state)
{
if((state != 0) != (PTTLevel != 0))
outportb(PTTPort,inportb(PTTPort) | PTTBit);
else
outportb(PTTPort,inportb(PTTPort) & ~PTTBit);
ShowTXRX(state,FALSE);
}
/* ----- Transmit Queue Manipulation ----- */
/* TXQInit()
Initializes the level 1 transmit queue.
*/
void TXQInit()
{
TXQBytes = TXQSize = 0; /* empty queue */
}
/* TXQAdd(packet)
Adds a packet to the TXQueue. Returns TRUE if successful, or
FALSE if error.
Computes and sets CRC for packet.
'packet' is a pointer to an AX.25 level 1 packet record, that was
alloced with the malloc() function.
*/
int TXQAdd(struct ax25_level1 *packet)
{
/* check for full queue */
if(TXQSize >= MAXTXQUEUE)
return FALSE;
/* compute and set CRC */
(void) CRCCheck(packet);
/* add to TXQueue */
TXQBytes += packet->len;
TXQueue[TXQSize++] = packet;
return TRUE;
}
/* TXQEmpty()
Assumes a clear channel, keys transmitter and empties TX queue.
Frees all TX queue entries.
*/
void TXQEmpty()
{
word from;
int i;
/* is there anything in the queue to send? */
if(TXQSize) {
TXKey(TRUE); /* key up transmitter */
from = timer(); /* get current time */
bitsent = 0; /* clear bit sent count */
disable(); /* kill interrupts */
/* send all packets in the TX Queue */
from = sendflags(from,TXStartFlags); /* send flags */
for(i=0; i<TXQSize; i++) {
from = sendpacketdata(from,TXQueue[i]);
from = sendflags(from,TXEndFlags);
}
TXKey(FALSE); /* drop transmitter key */
enable(); /* interrupts allowed */
/* attempt to re-adjust the BIOS clock */
ClockAdjust(bitsent);
/* free all packets in the TX Queue */
for(i=0; i<TXQSize; i++) {
#ifdef TRACE
if(DebugMode)
LogPacket(TXQueue[i],2); /* log the packet */
#endif
free(TXQueue[i]);
}
TXCount += TXQSize;
TXQBytes = TXQSize = 0;
}
}
/* TXQBytesInQ()
Returns the number of bytes currently in the Level 1 TX queue.
*/
int TXQBytesInQ(void)
{
return TXQBytes;
}